﻿using System;
using System.Text;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;
using System.Net.Sockets;
using RedCorona.Net;
using RedCorona.Cryptography;
using System.Threading;
using Silmoon;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using Silmoon.Threading;
using Levi.Finance.Server;
using Levi.Finance.Server.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Utilities;

namespace Levi.Finance.Server.Common
{
	public unsafe class ABC : Silmoon.MySilmoon.SilmoonProductGBCInternat, Silmoon.MySilmoon.IRunningAble
	{
		public RedCorona.Net.Server server;
		public ClientInfo client;
		public NameValueCollection Parameters = SmString.AnalyzeNameValue(Environment.GetCommandLineArgs(), "=", "--");
		public Data.MongoDB mongo = null;
		public Configure configure = null;
		public Thread tcpSocketThread;

		public ABC()
		{
			InitProductInfo("LeviFinanceServer", "0.0.0.1");
			this.OnThreadException += new System.Threading.ThreadExceptionEventHandler(ABC_OnThreadException);
		}

		void ABC_OnThreadException(object sender, ThreadExceptionEventArgs e)
		{
			if (configure.server_setting_debug == false)
				return;
			Console.ForegroundColor = ConsoleColor.Red;
			Console.WriteLine("===============================================================================");
			Console.ForegroundColor = ConsoleColor.DarkRed;
			Console.WriteLine(e.Exception.ToString());
			Console.ForegroundColor = ConsoleColor.Red;
			Console.WriteLine("===============================================================================");
			Console.ResetColor();
		}

		bool ClientEvent(RedCorona.Net.Server serv, ClientInfo new_client)
		{
			new_client.MessageType = MessageType.CodeAndLength;
			new_client.SendMessage(0x01020304, new byte[] { 0, 1, 2, 3, 4 }, 0);
			new_client.SendMessage(0x11111111, new byte[] { 0, 0, 4, 23 }, ParameterType.Int);
			new_client.OnReadMessage += new ConnectionReadMessage(ReadMessage);
			return true;
			// allow this connection
		}

		void ReadData(ClientInfo ci, String text)
		{
			Console.WriteLine("Received from " + ci.ID + ": " + text);
			Package pack = JsonConvert.DeserializeObject<Package>(text);
			if (text[0] == '!')
			{
				server.Broadcast(Encoding.Default.GetBytes(text));
			}
			else
			{
				Console.WriteLine(pack.opt);
				Console.WriteLine(pack.username);
				Console.WriteLine(pack.password);
				Result result = new Result();
				result.status = 1;
				result.data = null;
				result.info = "登录成功！".ToString();
				ci.SendMessage(0xABCDEF01, Encoding.Default.GetBytes(JsonConvert.SerializeObject(result)));
			}
		}

		void ReadMessage(ClientInfo ci, uint co, byte[] by, int length)
		{
			Console.WriteLine("Received from " + ci.ID + " " + length + "byte");
			try
			{
				byte[] copy = new byte[1];
				System.Array.Copy(by, 4, copy, 0, 1);
				//int len =  (int)copy[0];
				byte[] msg = new byte[copy[0]];
				System.Array.Copy(by, 5, msg, 0, copy[0]);
				string text = Encoding.Default.GetString(msg);
				Package pack = JsonConvert.DeserializeObject<Package>(text);
				Console.WriteLine(pack.opt);
				Console.WriteLine(pack.username);
				Console.WriteLine(pack.password);
				MongoCursor<BsonDocument> collection = null;
				Result result = new Result();
				switch (pack.opt)
				{
					case 1:
						IMongoQuery query = null;
						MongoDB.Driver.Builders.QueryComplete queryAdmin = global::MongoDB.Driver.Builders.Query.EQ("username", pack.username);
						query = global::MongoDB.Driver.Builders.Query.And(queryAdmin);
						collection = mongo.GetList("user", query);
						//Result result = new Result();
						bool status = false;
						result.opt = pack.opt;
						foreach (var row in collection)
						{
							string pwd = Silmoon.Security.SmHash.Get32MD5(pack.password);
							string opwd = (string)row["password"];
							if (opwd.ToUpper() == pwd.ToUpper())
							{
								status = true;
								result.status = 1;
								result.data = null;
								result.info = "登录成功！".ToString();
								ci.SendMessage(0xABCDEF01, Encoding.Default.GetBytes(JsonConvert.SerializeObject(result)), ParameterType.Int);
							}
							else
							{
								result.status = -1;
								result.data = null;
								result.info = "用户名或密码错误！";
								ci.SendMessage(0xABCDEF01, Encoding.Default.GetBytes(JsonConvert.SerializeObject(result)), ParameterType.Int);
							}
						}
						if (status == false)
						{
							result.status = -1;
							result.data = null;
							result.info = "用户名或密码错误！";
							ci.SendMessage(0xABCDEF01, Encoding.Default.GetBytes(JsonConvert.SerializeObject(result)), ParameterType.Int);
						}
						break;
					case 2:
						if(pack.data == null){
							collection = mongo.GetList("finance");
							ArrayList array = new ArrayList();
							foreach(var row in collection){
								Finance f = new Finance();
								f.id = row["_id"].ToString();
								f.remark = row["remark"].ToString();
								f.income = row["income"].ToInt32();
								f.money = row["money"].ToString();
								f.total = row["total"].ToString();
								f.createTime = row["create_time"].ToInt32();
								array.Add(f);
								f = null;
							}
							result.status = 1;
							result.opt = pack.opt;
							result.data = array;
							result.info = "加载成功！";
							ci.SendMessage(0xABCDEF01, Encoding.Default.GetBytes(JsonConvert.SerializeObject(result)), ParameterType.Int);
						}
						break;
					default:
						break;
				}
			}
			catch (Exception e)
			{
				Console.WriteLine(e.ToString());
			}
		}

		public bool Start()
		{
			if (RunningState == Silmoon.MySilmoon.RunningState.Running)
				return false;
			RunningState = Silmoon.MySilmoon.RunningState.Running;
			configure = new Configure(this);
			mongo = new Data.MongoDB(this);
			server = new RedCorona.Net.Server(this);
			server.DefaultEncryptionType = EncryptionType.ServerRSAClientKey;
			server.ClientReady += new ClientEvent(ClientEvent);

			Threads.ExecAsync(mongo.OpenMongoDBA, this.onThreadException);
			tcpSocketThread = Threads.ExecAsync(server.StartA, this.onThreadException);
			Threads.ExecAsync(mongo.OpenMongoDBA, this.onThreadException);

			return true;
		}

		public void StartA()
		{
			Start();
		}

		public bool Suspend()
		{
			return false;
		}

		public bool Resume()
		{
			return false;
		}

		public bool Stop()
		{
			if (RunningState == Silmoon.MySilmoon.RunningState.Stopped)
				return false;
			RunningState = Silmoon.MySilmoon.RunningState.Stopped;
			server.Dispose();
			mongo.Dispose();
			server = null;
			return true;
		}		
	}
}

